using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace KexpScrobbler.Kexp
{
    delegate void SongReadEventHandler(object sender, SongReadEventArgs e);
    delegate void SongReadFailedEventHandler(object sender, SongReadFailedEventArgs e);

    class KexpSongReader
    {
        const int bufferSize = 1024;
        const string playlistUri = "http://kexp.org/s/s.aspx";
        
        public event SongReadEventHandler SongRead;
        public event SongReadFailedEventHandler SongReadFailed;

        Regex getSongInformationRegex = new Regex("\\d+:\\d+ (.*?) - (.*?)\\</xml\\>", RegexOptions.Compiled);

        public void ReadSong()
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(playlistUri);

                KexpRequestState requestState = new KexpRequestState();
                requestState.Request = request;

                IAsyncResult result = (IAsyncResult)request.BeginGetResponse(new AsyncCallback(respCallback), requestState);
                if (requestState.Response != null)
                {
                    requestState.Response.Close();
                }
            }
            catch (WebException e)
            {
                OnSongReadRailed(new SongReadFailedEventArgs(e.Message + " " + e.Status.ToString()));
            }
            catch (Exception e)
            {
                OnSongReadRailed(new SongReadFailedEventArgs(e.Message));
            }
        }

        private void respCallback(IAsyncResult asynchronousResult)
        {
            try
            {
                KexpRequestState requestState = (KexpRequestState)asynchronousResult.AsyncState;
                HttpWebRequest request = requestState.Request;
                requestState.Response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);

                Stream responseStream = requestState.Response.GetResponseStream();
                requestState.StreamResponse = responseStream;

                IAsyncResult asynchronousInputRead = responseStream.BeginRead(requestState.BufferRead, 0, bufferSize, new AsyncCallback(readCallBack), requestState);
                return;
            }
            catch (WebException e)
            {
                OnSongReadRailed(new SongReadFailedEventArgs(e.Message + " " + e.Status.ToString()));
            }
        }

        private void readCallBack(IAsyncResult asyncResult)
        {
            try
            {
                KexpRequestState requestState = (KexpRequestState)asyncResult.AsyncState;
                Stream responseStream = requestState.StreamResponse;
                int read = responseStream.EndRead(asyncResult);

                if (read > 0)
                {
                    requestState.RequestData.Append(Encoding.ASCII.GetString(requestState.BufferRead, 0, read));
                    IAsyncResult asynchronousResult = responseStream.BeginRead(requestState.BufferRead, 0, bufferSize, new AsyncCallback(readCallBack), requestState);
                    return;
                }
                else
                {

                    string title = "";
                    string album = "";
                    string artist = "";
                    string label = "";
                    string dj = "";
                    string show = "";
                    int? releaseYear = null;

                    if (requestState.RequestData.Length > 1)
                    {
                        string stringContent = requestState.RequestData.ToString();

                        
                        XmlDocument doc = new XmlDocument();
                        try
                        {
                            doc.LoadXml(stringContent);

                            title = doc.SelectSingleNode("/k/t/s").InnerText;
                            album = doc.SelectSingleNode("/k/t/a").InnerText;
                            artist = doc.SelectSingleNode("/k/t/r").InnerText;
                            label = doc.SelectSingleNode("/k/t/l").InnerText;
                            dj = doc.SelectSingleNode("/k/s/d").InnerText;
                            show = doc.SelectSingleNode("/k/s/n").InnerText;

                            string ry = doc.SelectSingleNode("/k/t/ry").InnerText;

                            if (!string.IsNullOrEmpty(ry))
                            {
                                releaseYear = Int32.Parse(ry);
                            }
                        }
                        catch (XmlException)
                        { }

                        OnSongRead(new SongReadEventArgs(new SongInformation(title, album, artist, label,
                            releaseYear, dj, show, DateTime.Now)));
                    }

                    responseStream.Close();
                }
            }
            catch (WebException e)
            {
                OnSongReadRailed(new SongReadFailedEventArgs(e.Message + " " + e.Status.ToString()));
            }
        }

        protected void OnSongReadRailed(SongReadFailedEventArgs e)
        {
            if (SongReadFailed != null)
            {
                SongReadFailed(this, e);
            }
        }

        protected void OnSongRead(SongReadEventArgs e)
        {
            if (SongRead != null)
            {
                SongRead(this, e);
            }
        }
    }
}